package fr.umlv.escapeir.gesture;

import java.awt.geom.Ellipse2D;


public class Looping implements Mask {

	private static final int MIN_SIZE = 40;
	private static final int TOLERANCE = 30;
	private static final int HALF_TOLERANCE = TOLERANCE / 2;

	@Override
	public boolean isValid(Gesture g) {

		int indexMinX = g.indexMinX();
		int indexMaxX = g.indexMaxX();
		int indexMinY = g.indexMinY();
		int indexMaxY = g.indexMaxY();

		int xMin = g.getX(indexMinX); // Minimum value of X from Gesture g (argument)
		int xMax = g.getX(indexMaxX); // Maximum value of X from Gesture g (argument)
		int yMin = g.getY(indexMinY); // Minimum value of Y from Gesture g (argument)
		int yMax = g.getY(indexMaxY); // Maximum value of Y from Gesture g (argument)

		int width = xMax - xMin; // Width of the form define by the Gesture g (argument)
		int height = yMax - yMin; // Height of the form define by the Gesture g (argument)


		// Verify if the form is not too Oval
		if(Math.abs(width - height) < MIN_SIZE) { 

			// Verify if the form is not too little
			if(width > MIN_SIZE && height > MIN_SIZE) {
				Ellipse2D ellipseMax = new Ellipse2D.Double(xMin - HALF_TOLERANCE, yMin - HALF_TOLERANCE, width + TOLERANCE, height + TOLERANCE); 
				Ellipse2D ellipseMin = new Ellipse2D.Double(xMin + HALF_TOLERANCE, yMin + HALF_TOLERANCE, width - TOLERANCE, height - TOLERANCE); 

				// Verify if all point of Gesture g (argument) is include between 2 Ellipse
				for(int i = 0; i < g.size(); i++) {
					int x = g.getX(i);
					int y = g.getY(i);
					if(!(ellipseMax.contains(x, y) && !ellipseMin.contains(x, y))) return false;
				}

				int indexMin = minOfFour(indexMinY, indexMaxX, indexMaxY, indexMinX);
				int tabIndex[] = {indexMinY, indexMaxX, indexMaxY, indexMinX};
				boolean left = true;

				for(int i = 0; i < 3; i++) {
					if(tabIndex[(indexMin)%4] > tabIndex[(indexMin + 1)%4]) {
						left = false;
					}
					indexMin++;
				}

				if(left == true) { // Left == true is LeftLooping
					g.setGestureValid(Masks.LOOPING, Direction.LEFT);
					return true;
				}
				else { // Left == false is a RightLooping
					g.setGestureValid(Masks.LOOPING, Direction.RIGHT);
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * @param xMin
	 * @param xMax
	 * @param yMin
	 * @param yMax
	 * @return 0 if min is x0, 1 if min is x1, 2 if min is x2, 3 if min is x3
	 */
	private int minOfFour(int x0, int x1, int x2, int x3) {
		int tab[] = {x1, x2, x3};

		int min = x0;
		int returnIndex = 0;

		for(int i = 0; i < tab.length; i++){
			if(tab[i] < min) {
				min = tab[i];
				returnIndex = i + 1;
			}
		}
		return returnIndex;
	}
}